﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using Object = UnityEngine.Object;
using ScFramework.Core;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using ScFramework.Utilities;
using UnityEditor.UIElements;
using System.ComponentModel;

public class PropEditor : EditorWindow
{
    [MenuItem("Tools/预设参数设置 #Q")]
    public static void OpenWindow()
    {
        var window = EditorWindow.GetWindow<PropEditor>();
        var types=TypeUtilities.GetTypes(typeof(SComponent));
        window.typeTree.Add(typeof(SComponent), new TypeTree(typeof(SComponent)));
        foreach(var x in types)
        {
            window.typeTree.Add(x,new TypeTree(x));
        }
        window.GetPrefabs();
    }
    /// <summary>
    /// 窗体位置
    /// </summary>
    Vector2 lastScrollPos = Vector2.zero;
    DisplayType displayType;
    SortType sortType;
    Dictionary<Type, TypeTree> typeTree = new Dictionary<Type, TypeTree>();
    Dictionary<object, bool> isFold = new Dictionary<object, bool>();
    SComponent instance;
    public void OnEnable()
    {
        lastScrollPos = Vector2.zero;
    }
    /// <summary>
    /// 存放所有预设
    /// </summary>
    List<GameObject> prefabs = new List<GameObject>();
    private void OnGUI()
    {
        lastScrollPos = EditorGUILayout.BeginScrollView(lastScrollPos);
        displayType = (DisplayType)EditorGUILayout.EnumPopup("编辑模式", displayType);
        if (displayType == DisplayType.道具)
        {
            foreach (var x in prefabs)
            {
                isFold[x] = EditorGUILayout.InspectorTitlebar(isFold[x], x);
                if (isFold[x])
                {
                    string lastpath = default;
                    var comps = x.GetAll<SComponent>();
                    for (int i = 0; i < comps.Count; i++)
                    {
                        string nowpath = GetPath(x, comps[i]);
                        if (lastpath != nowpath)
                        {
                            EditorGUILayout.LabelField(nowpath);
                            lastpath = nowpath;
                        }
                       LayoutSComponent(comps[i]);
                    }
                }

            }
        }
        else if (displayType == DisplayType.组件)
        {
            LayoutSComponent(typeof(SComponent));
        }


        EditorGUILayout.EndScrollView();

    }
    /// <summary>
    /// 文件夹中读取预设gameobject
    /// </summary>
    /// <returns></returns>
    private void GetPrefabs()
    {
        var t = Resources.LoadAll<GameObject>("Prefab/Item/");
        foreach (var x in t)
        {
            if (!isFold.ContainsKey(x))
            {
                isFold.Add(x, false);
                prefabs.Add(x);
                var coms=x.GetAll<SComponent>();
                foreach(var q in coms)
                {
                    typeTree[q.GetType()].coms.Add(q);
                }
            }
        }
        instance = Resources.Load<GameObject>("Prefab/Item/Core").GetComponent<SComBody>() ;
    }
    /// <summary>
    /// 递归展示继承层级
    /// </summary>
    /// <param name="type"></param>
    private void LayoutSComponent(Type type)
    {
        if (type == typeof(SComponent))
        {
            foreach (var y in typeTree[type].sons)
            {
                LayoutSComponent(y);
            }
            return;
        }
        if (typeTree[type].sons.Count + typeTree[type].coms.Count > 0)
        {
            if (!isFold.ContainsKey(type))
            {
                isFold.Add(type, false);
            }
            isFold[type] = (EditorGUILayout.Foldout(isFold[type], new GUIContent(type.ToString())));
            if (isFold[type])
            {
                if (typeTree[type].coms.Count != 0)
                {
                    EditorGUILayout.BeginHorizontal();
                    GUILayout.Space(20);
                    EditorGUILayout.BeginVertical();
                    foreach (var x in typeTree[type].coms)
                    {
                        if (x.GetType() == type)
                        {
                             LayoutSComponent(x);
                        }
                    }
                    EditorGUILayout.EndVertical();
                    EditorGUILayout.EndHorizontal();
                }
                if (typeTree[type].sons.Count != 0)
                {
                    if (isFold[type])
                    {
                        EditorGUILayout.BeginHorizontal();
                        GUILayout.Space(20);
                        EditorGUILayout.BeginVertical();
                        foreach (var y in typeTree[type].sons)
                        {
                            LayoutSComponent(y);
                        }
                        EditorGUILayout.EndVertical();
                        EditorGUILayout.EndHorizontal();
                    }
                }

            }
        }
        else if (typeTree[type].coms.Count != 0)
        {
            if (typeTree[type].coms.Count != 0)
            {
                if (!isFold.ContainsKey(type))
                {
                    isFold.Add(type, false);

                }
                isFold[type] = (EditorGUILayout.Foldout(isFold[type], new GUIContent(type.ToString())));
                if (isFold[type])
                {
                    EditorGUILayout.BeginHorizontal();
                    GUILayout.Space(20);
                    EditorGUILayout.BeginVertical();
                    foreach (var x in typeTree[type].coms)
                    {
                        if (x.GetType() == type)
                        {
                            LayoutSComponent(x);
                        }
                    }
                    EditorGUILayout.EndVertical();
                    EditorGUILayout.EndHorizontal();
                }
            }
        }
        else if(typeTree[type].sons.Count>0)
        {
            if (!isFold.ContainsKey(type))
            {
                isFold.Add(type, false);
            }
            isFold[type] = (EditorGUILayout.Foldout(isFold[type], new GUIContent(type.ToString())));
            if (isFold[type])
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(20);
                EditorGUILayout.BeginVertical();
                foreach (var y in typeTree[type].sons)
                {
                    LayoutSComponent(y);
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndHorizontal();
            }
        }
    }
    /// <summary>
    /// 展示组件内容 
    /// </summary>
    /// <param name="com"></param>
    private void LayoutSComponent(SComponent com)
    {
        if (!isFold.ContainsKey(com))
        {
            isFold.Add(com, false);
            return;
        }
        EditorGUILayout.BeginHorizontal();
        GUILayout.Space(20);
        EditorGUILayout.BeginVertical();
        bool flag = false;
        if (displayType == DisplayType.道具)
        {
            isFold[com] = EditorGUILayout.InspectorTitlebar(isFold[com], com);
        }
        else if (displayType == DisplayType.组件)
        {
            string path = GetPath(GetRoot(com.gameObject), com);
            if (EditorGUILayout.DropdownButton(new GUIContent(path), FocusType.Passive))
            {
                isFold[com] = !isFold[com];
            }
        }
        if (isFold[com])
        {
            var fields = com.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (var x in fields)
            {
                 LayoutField(x, com);
            }
        }
        EditorGUILayout.EndVertical();
        EditorGUILayout.EndHorizontal();
    }
    /// <summary>
    /// 展示数据
    /// </summary>
    /// <param name="data"></param>
    /// <param name="com"></param>
    /// <returns></returns>
    private void LayoutField(FieldInfo data, Object com)
    {
        if (data.IsDefined<HideInInspector>(true))
        {
            return;
        }
        var name = data.IsDefined<HeaderAttribute>(true) ? data.GetAttribute<HeaderAttribute>().header : data.Name;
        var value = ValueUtil.Get(data.FieldType);
        if (value != null)
        {
            object info = data.GetValue(com);
            value.LayoutField(name, ref info);
            if (!value.CompareEqual(data.GetValue(com),info))
            {
                data.SetValue(com, info);
            }
        }
        else
        {
            EditorGUILayout.LabelField($"{data.FieldType}没有对应类型");
        }
    }
    /// <summary>
    /// 返回组件路径
    /// </summary>
    /// <param name="root"></param>
    /// <param name="com"></param>
    /// <returns></returns>
    private string GetPath(GameObject root, SComponent com)
    {
        List<string> names = new List<string>();
        GameObject tem = com.gameObject;
        while (tem.name != root.name)
        {
            //    Debug.LogError(tem.name);
            names.Add(tem.name);
            tem = com.gameObject.transform.parent.gameObject;
        }
        string path = root.name;
        if (names.Count == 0)
        {
            return path;
        }
        else
        {
            for (int i = names.Count; i > 0; i--)
            {
                //    Debug.LogError(names[i-1]);
                path = path + $"/{names[i - 1]}";
            }
            return path;
        }
    }
    /// <summary>
    /// 返回最大父级物体
    /// </summary>
    /// <param name="son"></param>
    /// <returns></returns>
    private GameObject GetRoot(GameObject son)
    {
        GameObject tem = son;
        while (tem.transform.parent != null)
        {
            tem = tem.transform.parent.gameObject;
        }
        return tem;
    }
    /*private void SortList(SortType type)
    {
        if (type == SortType.升序)
        {
            componentsDIC.Sort((Tuple<Type, List<SComponent>> t1, Tuple<Type, List<SComponent>> t2)
                => t1.Item2.Count.CompareTo(t2.Item2.Count));
        }else if (type == SortType.降序)
        {
            componentsDIC.Sort((Tuple<Type, List<SComponent>> t1, Tuple<Type, List<SComponent>> t2)
                => t2.Item2.Count.CompareTo(t1.Item2.Count));
        }else
        {
            componentsDIC.Sort((Tuple<Type, List<SComponent>> t1, Tuple<Type, List<SComponent>> t2)
                => t2.Item1.ToString().CompareTo(t1.Item2.ToString()));
        }
    }*/
    /// <summary>
    /// 两种展示模式
    /// </summary>
    private enum DisplayType
    {
        道具,
        组件
    }
    private enum SortType
    {
        降序,
        升序,
        字典序
    }
    private class TypeTree
    {
        public Type parent;
        public List<Type> sons;
        public List<SComponent> coms;
        public TypeTree(Type type) 
        {
            parent = type.BaseType;
            sons = new List<Type>();
            coms = new List<SComponent>();
            var nams= TypeUtilities.GetTypes(type);
           
            foreach(var x in nams)
            {
                if (x.BaseType == type)
                {
                    sons.Add(x);
                }
            }
        }

    }




}
